﻿using System.Collections.Generic;

namespace Basic
{
    /// <summary>
    /// LinkedListExtension
    /// </summary>
    public static class LinkedListExtension
    {
        /// <summary>
        /// 将元素插入到有序链表中, 插入位置由funcOrder决定
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="this">链表</param>
        /// <param name="data">待插入元素</param>
        /// <param name="funcOrder">比较目标值与链表内的元素的前后关系: 小于0，在前面; 等于0, 位置一致; 大于0, 在后面></param>
        public static void InsertInOrder<T>(this LinkedList<T> @this, T data, System.Func<T, T, int> funcOrder)
        {
            var p = @this.First;
            while (p != null)
            {
                var tmp = funcOrder(p.Value, data);
                if (tmp <= 0)
                {
                    @this.AddBefore(p, data);
                    return;
                }
                p = p.Next;
            }

            @this.AddLast(data);
        }

        /// <summary>
        /// 在有序链表中, 移除指定data
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="this"></param>
        /// <param name="data"></param>
        /// <param name="funcOrder">比较目标值与链表内的元素的前后关系: 小于0，在前面; 等于0, 位置一致; 大于0, 在后面</param>
        public static bool RemoveInOrder<T>(this LinkedList<T> @this, T data, System.Func<T, T, int> funcOrder)
        {
            var p = @this.First;
            while (p != null)
            {
                var tmp = funcOrder(p.Value, data);
                if (tmp == 0)
                {
                    @this.Remove(p);
                    return true;
                }
                else if (tmp > 0)
                {
                    return false;
                }
                p = p.Next;
            }
            return false;
        }

        /// <summary>
        /// 在有序链表中, 查找指定data
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="this"></param>
        /// <param name="data"></param>
        /// <param name="funcOrder"></param>
        public static LinkedListNode<T> FindInOrder<T>(this LinkedList<T> @this, T data, System.Func<T, T, int> funcOrder)
        {
            var p = @this.First;
            while (p != null)
            {
                var tmp = funcOrder(p.Value, data);
                if (tmp == 0)
                {
                    return p;
                }
                else if (tmp > 0)
                {
                    return null;
                }
                p = p.Next;
            }
            return null;
        }
    }
}
